import java.util.logging.Logger
import org.semanticweb.owlapi.apibinding.OWLManager
import org.semanticweb.owlapi.model.*
import org.semanticweb.owlapi.reasoner.*
import org.semanticweb.owlapi.profiles.*
import org.semanticweb.owlapi.util.*
import org.mindswap.pellet.KnowledgeBase
import org.mindswap.pellet.expressivity.*
import org.mindswap.pellet.*
import org.semanticweb.owlapi.io.*
import org.semanticweb.elk.owlapi.*

def yeastpfile = new File("flyphenotypes.txt")
def yeastgfile = new File("gene_association.fb")
def flyontology = new File("flybase_controlled_vocabulary_xp.obo")

def classicalallele = new File("Dmel_classical_alleles")

def fullinfo = new File("allele_pc_ref.tsv")

def go2name = [:]
def readGo = { File f ->
  f.splitEachLine("\t") { line ->
    def id = line[0]
    def name = line[1]
    go2name[id] = name
  }
}
readGo(new File("cellular_component.tbl"))
readGo(new File("biological_process.tbl"))
readGo(new File("molecular_function.tbl"))

def gene2name = [:]

def al2gene = [:]
def clallele = [:]
classicalallele.splitEachLine("\t") { line ->
  def al = line[2]?.trim()
  def g = line[0]?.trim()
  al2gene[al] = g
  if (al!=null && g!=null) {
    clallele[al] = g
  }
  gene2name[line[0]] = line[1]
}

def g2info = [:]
fullinfo.splitEachLine("\t") { line ->
  def al = line[1]
  def g = al2gene[al]
  def info = line[5]
  if (g) {
    if (g2info[g] == null) {
      g2info[g] = new TreeSet()
    }
    if (info) {
      g2info[g].add(info)
    }
  }
}


def termid = ""
def fb2go = [:]
flyontology.eachLine { line ->
  if (line.startsWith("id:")) {
    termid = line.substring(3).trim()
  }
  if (line.indexOf("intersection")>-1 && line.indexOf("GO:")>-1) {
    line = line.substring(line.indexOf("GO:"), line.indexOf("GO:")+10).trim()
    fb2go[termid] = line
  }
}


def onturi = "http://bioonto.de/pgkb.owl#"

OWLOntologyManager manager = OWLManager.createOWLOntologyManager()

OWLDataFactory fac = manager.getOWLDataFactory()
def factory = fac

OWLOntology ont = manager.loadOntologyFromOntologyDocument(new File("gene_ontology_ext.obo"))
def ontology = ont

def id2class = [:] // maps an OBO-ID to an OWLClass
ontology.getClassesInSignature(true).each {
  def a = it.toString()
  a = a.substring(a.indexOf("obo/")+4,a.length()-1)
  a = a.substring(a.indexOf('#')+1)
  a = a.replaceAll("_",":")
  a = a.replaceAll("tp://bio2rdf.org/","")
  if (id2class[a] == null) {
    id2class[a] = it
  }
}

OWLReasonerFactory reasonerFactory = null

ConsoleProgressMonitor progressMonitor = new ConsoleProgressMonitor()
OWLReasonerConfiguration config = new SimpleConfiguration(progressMonitor)

OWLReasonerFactory f1 = new ElkReasonerFactory()
OWLReasoner reasoner = f1.createReasoner(ont,config)

reasoner.precomputeInferences(InferenceType.CLASS_HIERARCHY)

def processes = reasoner.getSubClasses(id2class["GO:0008150"], false).getFlattened()
def functions = reasoner.getSubClasses(id2class["GO:0003674"], false).getFlattened()
def cellparts = reasoner.getSubClasses(id2class["GO:0005575"], false).getFlattened()
def behavior = reasoner.getSubClasses(id2class["GO:0007610"], false).getFlattened() // CHANGE HERE

def yp2go = [:]
yeastpfile.splitEachLine("\t") { line ->
  def id = line[0]
  def pheno = line[1]
  //    if (id in clallele.keySet()) {
  //      id = clallele[id]
    if (fb2go[pheno]!=null) {
      if (yp2go[id] == null) {
	yp2go[id] = new TreeSet()
      }
      if (id.indexOf("FBgn")>-1) {
	yp2go[id].add(fb2go[pheno])
      }
    }
    //  }
}

def yg2go = [:]
yeastgfile.splitEachLine("\t") { line ->
  if (!line[0].startsWith("!")) {
    def id = line[1]
    def go = line[4]
    def ev = line[6]
    if (ev == "EXP" || ev == "IDA" || ev == "IPI" || ev == "IMP" || ev == "IGI" || ev == "IEP") {
    if (go!=null && go.length()>2 && go.startsWith("GO")) {
      if (yg2go[id] == null) {
	yg2go[id] = new TreeSet()
      }
      yg2go[id].add(go)
    }
    }
  }
}
def yg2goclosed = [:] // close against GO taxonomy
yg2go.keySet().each { sgd ->
  yg2goclosed[sgd] = new TreeSet()
  def gos = yg2go[sgd]
  gos.each { go ->
    yg2goclosed[sgd].add(go)
    if (id2class[go]!=null) {
      reasoner.getSuperClasses(id2class[go], false).getFlattened().each { 
	def a = it.toString()
	a = a.substring(a.indexOf("obo/")+4,a.length()-1)
	a = a.substring(a.indexOf('#')+1)
	a = a.replaceAll("_",":")
	if (a.startsWith("GO")) {
	  yg2goclosed[sgd].add(a)
	}
      }
    }
  }
}

def fout = new PrintWriter(new BufferedWriter(new FileWriter("fly-new-go.txt")))
def match = 0
def mismatch = 0
yp2go.keySet().each { sgd ->
  def gop = yp2go[sgd]
  def gog = yg2goclosed[sgd]
  if (gog!=null && gog.size()>0) {
    gop.each { go ->
      //      if (id2class[go] in behavior) {
	if (go in gog) {
	  match+=1
	} else {
	  mismatch+=1
	  fout.print("$sgd\t")
	  //	  fout.print(gene2name[sgd]+"\t")
	  fout.print("$go\t")
	  fout.print(go2name[go]+"\t")
	  g2info[sgd]?.each { fout.print(it+"\t") }
	  fout.println("")
	}
	//      }
    }
  }
}
def total = match+mismatch
println "Total: "+total
println "Matches: $match ("+(match*100/total)+"%)"
println "Mismatches: $mismatch ("+(mismatch*100/total)+"%)"
fout.flush()
fout.close()

System.exit(0)
